package handler

import (
	"net/http"

	"vod-service/config" // 替换为实际项目路径

	"github.com/gin-gonic/gin"
	"github.com/volcengine/volc-sdk-golang/service/vod/models/request"
	"google.golang.org/protobuf/types/known/wrapperspb"
)

// ------------------------------ 媒资信息管理 ------------------------------

// 1. 获取媒资信息请求参数
type GetMediaInfosRequest struct {
	Vids string `form:"vids" binding:"required" example:"vid1,vid2"` // 媒资ID列表（逗号分隔）
}

// 获取媒资信息
func GetMediaInfosHandler(c *gin.Context) {
	var req GetMediaInfosRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodGetMediaInfosRequest{
		Vids: req.Vids,
	}

	resp, _, err := config.GetVodInstance().GetMediaInfos20230701(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "获取媒资信息失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 2. 更新媒资信息请求参数
type UpdateMediaInfoRequest struct {
	Vid              string `json:"vid" binding:"required"`      // 媒资ID
	PosterUri        string `json:"poster_uri,omitempty"`        // 封面URI（可选）
	Title            string `json:"title,omitempty"`             // 标题（可选）
	Description      string `json:"description,omitempty"`       // 描述（可选）
	Tags             string `json:"tags,omitempty"`              // 标签（可选）
	ClassificationId int64  `json:"classification_id,omitempty"` // 分类ID（可选）
	ExpireTime       string `json:"expire_time,omitempty"`       // 过期时间（可选，格式：yyyy-MM-ddTHH:mm:ssZ）
}

// 更新媒资信息
func UpdateMediaInfoHandler(c *gin.Context) {
	var req UpdateMediaInfoRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodUpdateMediaInfoRequest{
		Vid:              req.Vid,
		PosterUri:        wrapperspb.String(req.PosterUri),
		Title:            wrapperspb.String(req.Title),
		Description:      wrapperspb.String(req.Description),
		Tags:             wrapperspb.String(req.Tags),
		ClassificationId: wrapperspb.Int64(req.ClassificationId),
		ExpireTime:       wrapperspb.String(req.ExpireTime),
	}

	resp, _, err := config.GetVodInstance().UpdateMediaInfo(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "更新媒资信息失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 3. 修改媒资发布状态请求参数
type UpdateMediaPublishStatusRequest struct {
	Vid    string `json:"vid" binding:"required"`                                // 媒资ID
	Status string `json:"status" binding:"required,oneof=Published Unpublished"` // 状态（Published/Unpublished）
}

// 修改媒资发布状态
func UpdateMediaPublishStatusHandler(c *gin.Context) {
	var req UpdateMediaPublishStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodUpdateMediaPublishStatusRequest{
		Vid:    req.Vid,
		Status: req.Status,
	}

	resp, _, err := config.GetVodInstance().UpdateMediaPublishStatus(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "修改发布状态失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 4. 修改媒资存储类型请求参数
type UpdateMediaStorageClassRequest struct {
	Vids         string `json:"vids" binding:"required"`          // 媒资ID列表（逗号分隔）
	FileIds      string `json:"file_ids,omitempty"`               // 文件ID列表（逗号分隔，可选）
	StorageClass string `json:"storage_class" binding:"required"` // 存储类型（Standard/IA/Archive）
	CallbackArgs string `json:"callback_args,omitempty"`          // 回调参数（可选）
}

// 修改媒资存储类型
func UpdateMediaStorageClassHandler(c *gin.Context) {
	var req UpdateMediaStorageClassRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodUpdateMediaStorageClassRequest{
		Vids:         req.Vids,
		FileIds:      req.FileIds,
		StorageClass: req.StorageClass,
		CallbackArgs: req.CallbackArgs,
	}

	resp, _, err := config.GetVodInstance().UpdateMediaStorageClass(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "修改存储类型失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 5. 获取封面候选结果请求参数
type GetRecommendedPosterRequest struct {
	Vids string `form:"vids" binding:"required"` // 媒资ID列表（逗号分隔）
}

// 获取封面候选结果
func GetRecommendedPosterHandler(c *gin.Context) {
	var req GetRecommendedPosterRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodGetRecommendedPosterRequest{
		Vids: req.Vids,
	}

	resp, _, err := config.GetVodInstance().GetRecommendedPoster(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "获取封面候选失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 6. 删除完整媒资请求参数
type DeleteMediaRequest struct {
	Vids         string `json:"vids" binding:"required"` // 媒资ID列表（逗号分隔）
	CallbackArgs string `json:"callback_args,omitempty"` // 回调参数（可选）
}

// 删除完整媒资
func DeleteMediaHandler(c *gin.Context) {
	var req DeleteMediaRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodDeleteMediaRequest{
		Vids:         req.Vids,
		CallbackArgs: req.CallbackArgs,
	}

	resp, _, err := config.GetVodInstance().DeleteMedia(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "删除媒资失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 7. 删除媒体处理输出文件请求参数
type DeleteTranscodesRequest struct {
	Vid          string `json:"vid" binding:"required"`      // 媒资ID
	FileIds      string `json:"file_ids" binding:"required"` // 文件ID列表（逗号分隔）
	CallbackArgs string `json:"callback_args,omitempty"`     // 回调参数（可选）
}

// 删除媒体处理输出文件
func DeleteTranscodesHandler(c *gin.Context) {
	var req DeleteTranscodesRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodDeleteTranscodesRequest{
		Vid:          req.Vid,
		FileIds:      req.FileIds,
		CallbackArgs: req.CallbackArgs,
	}

	resp, _, err := config.GetVodInstance().DeleteTranscodes(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "删除处理文件失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 8. 删除素材文件请求参数
type DeleteMaterialRequest struct {
	Mid       string `json:"mid" binding:"required"`        // 素材ID
	SpaceName string `json:"space_name" binding:"required"` // 空间名称
}

// 删除素材文件
func DeleteMaterialHandler(c *gin.Context) {
	var req DeleteMaterialRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodDeleteMaterialRequest{
		Mid:       req.Mid,
		SpaceName: req.SpaceName,
	}

	resp, _, err := config.GetVodInstance().DeleteMaterial(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "删除素材失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// ------------------------------ 音视频信息查询 ------------------------------

// 9. 获取音视频信息请求参数
type GetMediaListRequest struct {
	SpaceName         string `form:"space_name" binding:"required"` // 空间名称
	Vid               string `form:"vid,omitempty"`                 // 媒资ID（可选）
	Status            string `form:"status,omitempty"`              // 状态（可选）
	Order             string `form:"order,omitempty"`               // 排序（可选，desc/asc）
	Tags              string `form:"tags,omitempty"`                // 标签（可选）
	StartTime         string `form:"start_time,omitempty"`          // 开始时间（可选）
	EndTime           string `form:"end_time,omitempty"`            // 结束时间（可选）
	Offset            string `form:"offset,omitempty"`              // 偏移量（可选，默认0）
	PageSize          string `form:"page_size,omitempty"`           // 页大小（可选，默认10）
	ClassificationIds string `form:"classification_ids,omitempty"`  // 分类ID列表（可选）
	TosStorageClasses string `form:"tos_storage_classes,omitempty"` // 存储类型（可选）
	VodUploadSources  string `form:"vod_upload_sources,omitempty"`  // 上传来源（可选）
}

// 获取音视频信息
func GetMediaListHandler(c *gin.Context) {
	var req GetMediaListRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodGetMediaListRequest{
		SpaceName:         req.SpaceName,
		Vid:               req.Vid,
		Status:            req.Status,
		Order:             req.Order,
		Tags:              req.Tags,
		StartTime:         req.StartTime,
		EndTime:           req.EndTime,
		Offset:            req.Offset,
		PageSize:          req.PageSize,
		ClassificationIds: req.ClassificationIds,
		TosStorageClasses: req.TosStorageClasses,
		VodUploadSources:  req.VodUploadSources,
	}

	resp, _, err := config.GetVodInstance().GetMediaList(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "获取音视频信息失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// ------------------------------ 字幕管理 ------------------------------

// 10. 获取字幕文件请求参数
type GetSubtitleInfoListRequest struct {
	Vid         string `form:"vid" binding:"required"` // 媒资ID
	FileIds     string `form:"file_ids,omitempty"`     // 文件ID列表（可选）
	Languages   string `form:"languages,omitempty"`    // 语言（可选）
	Formats     string `form:"formats,omitempty"`      // 格式（可选）
	LanguageIds string `form:"language_ids,omitempty"` // 语言ID（可选）
	SubtitleIds string `form:"subtitle_ids,omitempty"` // 字幕ID（可选）
	Status      string `form:"status,omitempty"`       // 状态（可选）
	Title       string `form:"title,omitempty"`        // 标题（可选）
	Tag         string `form:"tag,omitempty"`          // 标签（可选）
	Offset      string `form:"offset,omitempty"`       // 偏移量（可选）
	PageSize    string `form:"page_size,omitempty"`    // 页大小（可选）
	Ssl         string `form:"ssl,omitempty"`          // 是否HTTPS（可选，1/0）
}

// 获取字幕文件
func GetSubtitleInfoListHandler(c *gin.Context) {
	var req GetSubtitleInfoListRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodGetSubtitleInfoListRequest{
		Vid:         req.Vid,
		FileIds:     req.FileIds,
		Languages:   req.Languages,
		Formats:     req.Formats,
		LanguageIds: req.LanguageIds,
		SubtitleIds: req.SubtitleIds,
		Status:      req.Status,
		Title:       req.Title,
		Tag:         req.Tag,
		Offset:      req.Offset,
		PageSize:    req.PageSize,
		Ssl:         req.Ssl,
	}

	resp, _, err := config.GetVodInstance().GetSubtitleInfoList(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "获取字幕失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 11. 修改字幕发布状态请求参数
type UpdateSubtitleStatusRequest struct {
	Vid       string `json:"vid" binding:"required"`    // 媒资ID
	FileIds   string `json:"file_ids,omitempty"`        // 文件ID列表（可选）
	Languages string `json:"languages,omitempty"`       // 语言（可选）
	Formats   string `json:"formats,omitempty"`         // 格式（可选）
	Status    string `json:"status" binding:"required"` // 状态（Published/Unpublished）
}

// 修改字幕发布状态
func UpdateSubtitleStatusHandler(c *gin.Context) {
	var req UpdateSubtitleStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodUpdateSubtitleStatusRequest{
		Vid:       req.Vid,
		FileIds:   req.FileIds,
		Languages: req.Languages,
		Formats:   req.Formats,
		Status:    req.Status,
	}

	resp, _, err := config.GetVodInstance().UpdateSubtitleStatus(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "修改字幕状态失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 12. 更新字幕信息请求参数
type UpdateSubtitleInfoRequest struct {
	Vid      string `json:"vid" binding:"required"`      // 媒资ID
	FileId   string `json:"file_id" binding:"required"`  // 文件ID
	Language string `json:"language" binding:"required"` // 语言
	Format   string `json:"format" binding:"required"`   // 格式
	Title    string `json:"title,omitempty"`             // 标题（可选）
	Tag      string `json:"tag,omitempty"`               // 标签（可选）
}

// 更新字幕信息
func UpdateSubtitleInfoHandler(c *gin.Context) {
	var req UpdateSubtitleInfoRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodUpdateSubtitleInfoRequest{
		Vid:      req.Vid,
		FileId:   req.FileId,
		Language: req.Language,
		Format:   req.Format,
		Title:    wrapperspb.String(req.Title),
		Tag:      wrapperspb.String(req.Tag),
	}

	resp, _, err := config.GetVodInstance().UpdateSubtitleInfo(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "更新字幕信息失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 13. 签发字幕鉴权Token请求参数
type GetSubtitleAuthTokenRequest struct {
	Vid           string `form:"vid" binding:"required"`                  // 媒资ID
	ExpireSeconds int    `form:"expire_seconds" binding:"required,min=1"` // 过期时间（秒，至少1）
}

// 签发字幕鉴权Token
func GetSubtitleAuthTokenHandler(c *gin.Context) {
	var req GetSubtitleAuthTokenRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodGetSubtitleInfoListRequest{
		Vid: req.Vid,
	}

	token, err := config.GetVodInstance().GetSubtitleAuthToken(query, req.ExpireSeconds)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "签发字幕Token失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    gin.H{"token": token},
	})
}

// ------------------------------ 截图管理 ------------------------------

// 14. 获取截图结果请求参数
type ListSnapshotsRequest struct {
	Vid string `form:"vid" binding:"required"` // 媒资ID
}

// 获取截图结果
func ListSnapshotsHandler(c *gin.Context) {
	var req ListSnapshotsRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodListSnapshotsRequest{
		Vid: req.Vid,
	}

	resp, _, err := config.GetVodInstance().ListSnapshots(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "获取截图结果失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// ------------------------------ 跨空间迁移 ------------------------------

// 15. 提交跨空间文件迁移任务请求参数
type SubmitMoveObjectTaskRequest struct {
	SourceSpace      string `json:"source_space" binding:"required"`     // 源空间
	SourceFileName   string `json:"source_file_name" binding:"required"` // 源文件名
	TargetSpace      string `json:"target_space" binding:"required"`     // 目标空间
	TargetFileName   string `json:"target_file_name,omitempty"`          // 目标文件名（可选，默认同源文件名）
	SaveSourceObject bool   `json:"save_source_object,omitempty"`        // 是否保留源文件（可选，默认false）
	ForceOverwrite   bool   `json:"force_overwrite,omitempty"`           // 是否强制覆盖（可选，默认false）
}

// 提交跨空间文件迁移任务
func SubmitMoveObjectTaskHandler(c *gin.Context) {
	var req SubmitMoveObjectTaskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodSubmitMoveObjectTaskRequest{
		SourceSpace:      req.SourceSpace,
		SourceFileName:   req.SourceFileName,
		TargetSpace:      req.TargetSpace,
		TargetFileName:   req.TargetFileName,
		SaveSourceObject: req.SaveSourceObject,
		ForceOverwrite:   req.ForceOverwrite,
	}

	resp, _, err := config.GetVodInstance().SubmitMoveObjectTask(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "提交迁移任务失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 16. 查询跨空间文件迁移任务状态请求参数
type QueryMoveObjectTaskInfoRequest struct {
	TaskId      string `form:"task_id" binding:"required"`      // 任务ID
	SourceSpace string `form:"source_space" binding:"required"` // 源空间
	TargetSpace string `form:"target_space" binding:"required"` // 目标空间
}

// 查询跨空间文件迁移任务状态
func QueryMoveObjectTaskInfoHandler(c *gin.Context) {
	var req QueryMoveObjectTaskInfoRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodQueryMoveObjectTaskInfoRequest{
		TaskId:      req.TaskId,
		SourceSpace: req.SourceSpace,
		TargetSpace: req.TargetSpace,
	}

	resp, _, err := config.GetVodInstance().QueryMoveObjectTaskInfo(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "查询迁移任务状态失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// ------------------------------ 媒资分类管理 ------------------------------

// 17. 创建视频分类请求参数
type CreateVideoClassificationRequest struct {
	SpaceName      string `json:"space_name" binding:"required"`     // 空间名称
	Level          int    `json:"level" binding:"required,min=0"`    // 层级（0开始）
	ParentId       int64  `json:"parent_id" binding:"min=0"`         // 父分类ID（可选，默认0）
	Classification string `json:"classification" binding:"required"` // 分类名称
}

// 创建视频分类
func CreateVideoClassificationHandler(c *gin.Context) {
	var req CreateVideoClassificationRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodCreateVideoClassificationRequest{
		SpaceName:      req.SpaceName,
		Level:          int32(req.Level),
		ParentId:       req.ParentId,
		Classification: req.Classification,
	}

	resp, _, err := config.GetVodInstance().CreateVideoClassification(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "创建分类失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 18. 查询视频分类请求参数
type ListVideoClassificationsRequest struct {
	SpaceName        string `form:"space_name" binding:"required"`     // 空间名称
	ClassificationId int64  `form:"classification_id" binding:"min=0"` // 分类ID（可选，默认0查询所有）
}

// 查询视频分类
func ListVideoClassificationsHandler(c *gin.Context) {
	var req ListVideoClassificationsRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodListVideoClassificationsRequest{
		SpaceName:        req.SpaceName,
		ClassificationId: req.ClassificationId,
	}

	resp, _, err := config.GetVodInstance().ListVideoClassifications(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "查询分类失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 19. 更新视频分类请求参数
type UpdateVideoClassificationRequest struct {
	SpaceName        string `json:"space_name" binding:"required"`              // 空间名称
	ClassificationId int64  `json:"classification_id" binding:"required,min=1"` // 分类ID
	Classification   string `json:"classification" binding:"required"`          // 新分类名称
}

// 更新视频分类
func UpdateVideoClassificationHandler(c *gin.Context) {
	var req UpdateVideoClassificationRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodUpdateVideoClassificationRequest{
		SpaceName:        req.SpaceName,
		ClassificationId: req.ClassificationId,
		Classification:   req.Classification,
	}

	resp, _, err := config.GetVodInstance().UpdateVideoClassification(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "更新分类失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 20. 删除视频分类请求参数
type DeleteVideoClassificationRequest struct {
	SpaceName        string `json:"space_name" binding:"required"`              // 空间名称
	ClassificationId int64  `json:"classification_id" binding:"required,min=1"` // 分类ID
}

// 删除视频分类
func DeleteVideoClassificationHandler(c *gin.Context) {
	var req DeleteVideoClassificationRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodDeleteVideoClassificationRequest{
		SpaceName:        req.SpaceName,
		ClassificationId: req.ClassificationId,
	}

	resp, _, err := config.GetVodInstance().DeleteVideoClassification(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "删除分类失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// ------------------------------ DirectUrl模式接口 ------------------------------

// 21. 根据文件路径获取文件信息请求参数
type GetFileInfosRequest struct {
	SpaceName              string `form:"space_name" binding:"required"`         // 空间名称
	EncodedFileNames       string `form:"encoded_file_names" binding:"required"` // 编码后的文件名（逗号分隔）
	BucketName             string `form:"bucket_name,omitempty"`                 // 桶名称（可选）
	NeedDownloadUrl        bool   `form:"need_download_url,omitempty"`           // 是否需要下载地址（可选）
	DownloadUrlNetworkType string `form:"download_url_network_type,omitempty"`   // 下载地址网络类型（可选）
	DownloadUrlExpire      int    `form:"download_url_expire,omitempty"`         // 下载地址过期时间（可选，秒）
}

// 根据文件路径获取文件信息
func GetFileInfosHandler(c *gin.Context) {
	var req GetFileInfosRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    http.StatusBadRequest,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	query := &request.VodGetFileInfosRequest{
		SpaceName:              req.SpaceName,
		EncodedFileNames:       req.EncodedFileNames,
		BucketName:             req.BucketName,
		NeedDownloadUrl:        req.NeedDownloadUrl,
		DownloadUrlNetworkType: req.DownloadUrlNetworkType,
		DownloadUrlExpire:      int64(req.DownloadUrlExpire),
	}

	resp, _, err := config.GetVodInstance().GetFileInfos(query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    http.StatusInternalServerError,
			Message: "获取文件信息失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data:    resp,
	})
}

// 注册所有VOD相关路由
func RegisterVodRoutes(r *gin.Engine) {
	// 媒资信息管理
	mediaGroup := r.Group("/api/v1/vod/media")
	{
		mediaGroup.GET("/info", GetMediaInfosHandler)                      // 获取媒资信息
		mediaGroup.PUT("/info", UpdateMediaInfoHandler)                    // 更新媒资信息
		mediaGroup.PUT("/publish-status", UpdateMediaPublishStatusHandler) // 修改发布状态
		mediaGroup.PUT("/storage-class", UpdateMediaStorageClassHandler)   // 修改存储类型
		mediaGroup.GET("/poster/candidates", GetRecommendedPosterHandler)  // 获取封面候选
		mediaGroup.DELETE("", DeleteMediaHandler)                          // 删除完整媒资
		mediaGroup.DELETE("/transcodes", DeleteTranscodesHandler)          // 删除处理输出文件
	}

	// 素材管理
	materialGroup := r.Group("/api/v1/vod/material")
	{
		materialGroup.DELETE("", DeleteMaterialHandler) // 删除素材文件
	}

	// 音视频列表
	mediaListGroup := r.Group("/api/v1/vod/media-list")
	{
		mediaListGroup.GET("", GetMediaListHandler) // 获取音视频信息
	}

	// 字幕管理
	subtitleGroup := r.Group("/api/v1/vod/subtitle")
	{
		subtitleGroup.GET("", GetSubtitleInfoListHandler)             // 获取字幕文件
		subtitleGroup.PUT("/status", UpdateSubtitleStatusHandler)     // 修改字幕发布状态
		subtitleGroup.PUT("/info", UpdateSubtitleInfoHandler)         // 更新字幕信息
		subtitleGroup.GET("/auth-token", GetSubtitleAuthTokenHandler) // 签发字幕鉴权Token
	}

	// 截图管理
	snapshotGroup := r.Group("/api/v1/vod/snapshot")
	{
		snapshotGroup.GET("", ListSnapshotsHandler) // 获取截图结果
	}

	// 跨空间迁移
	moveGroup := r.Group("/api/v1/vod/move")
	{
		moveGroup.POST("task", SubmitMoveObjectTaskHandler)   // 提交迁移任务
		moveGroup.GET("task", QueryMoveObjectTaskInfoHandler) // 查询迁移任务状态
	}

	// 分类管理
	classificationGroup := r.Group("/api/v1/vod/classification")
	{
		classificationGroup.POST("", CreateVideoClassificationHandler)   // 创建分类
		classificationGroup.GET("", ListVideoClassificationsHandler)     // 查询分类
		classificationGroup.PUT("", UpdateVideoClassificationHandler)    // 更新分类
		classificationGroup.DELETE("", DeleteVideoClassificationHandler) // 删除分类
	}

	// DirectUrl模式
	directUrlGroup := r.Group("/api/v1/vod/direct-url")
	{
		directUrlGroup.GET("/file-info", GetFileInfosHandler) // 根据路径获取文件信息
	}
}
